Exceptions

The exception mechanism is intended to be usable by all GCC languages that have exceptions: Ada, C<#473#>++<#473#>, and Modula-3. The mechanism should be sufficiently uniform to allow multi-language programs to function in the presence of language-specific exceptions and exception handlers: for example, an Ada exception may propagate from a C<#474#>++<#474#> module to an Ada handler. The mechanism should also be zero cost, that is to say, there should be no run-time cost attached to the mere presence of a handler, only to the actual occurrence of an exception.

The design of exception handling is closely related to the semantics of finalization. Recall that on exit from any construct that declares some entities, there may be cleanup actions to perform: finalization of controlled objects, reclamation of local heap-allocated objects, etc. We implement this sequence of actions by means of a single chain that holds all local objects that may require finalization, and a single procedure that traverses this chain and invokes the appropriate finalization for each object therein. When an exception is raised, the stack must be unwound, and the finalization routines attached to each frame must be invoked in turn. The exception manager must be able to locate the exception handler, and then repeatedly unstack a frame and invoke its finalization procedure. The exception manager uses two tables for this purpose: an unwind table and a handler table.

<#2757#>Unwind Table.<#2757#>
The linker builds a table of address ranges, each of which is either under the control of a given exception handler, or has an attached finalization procedure. The table stores the addresses of each.

<#2758#>Handler table.<#2758#>
This table holds the list of exceptions managed by a particular handler.

The method depends on being able to find, without additional structures, the subprogram that contains the instruction that raised an exception. To insure that the processing is language-independent, the cleanup procedure is parameterless, and only its address needs to be retrievable.

Exception propagation proceeds as follows:

<#2759#>Locating the handler.<#2759#>
During this phase the exception manager uses the PC of the exception-raising instruction to locate the innermost active subprogram that has an applicable handler. This traversal of the stack is done without unwinding actions, so that the debugger can be invoked on the offending instruction in its proper context, in case there is no applicable handler.

<#2760#>Cleanup.<#2760#>
In the second phase, stack unwinding takes place, and the unwind table is used to retrieve the cleanup procedures at each step, until the exception handler takes control.